// +----------------------------------------------------------------------
// | ShopSuite商城系统 [ 赋能开发者，助力企业发展 ]
// +----------------------------------------------------------------------
// | 版权所有 随商信息技术（上海）有限公司
// +----------------------------------------------------------------------
// | 未获商业授权前，不得将本软件用于商业用途。禁止整体或任何部分基础上以发展任何派生版本、
// | 修改版本或第三方版本用于重新分发。
// +----------------------------------------------------------------------
// | 官方网站: https://www.shopsuite.cn  https://www.modulithshop.cn
// +----------------------------------------------------------------------
// | 版权和免责声明:
// | 本公司对该软件产品拥有知识产权（包括但不限于商标权、专利权、著作权、商业秘密等）
// | 均受到相关法律法规的保护，任何个人、组织和单位不得在未经本团队书面授权的情况下对所授权
// | 软件框架产品本身申请相关的知识产权，禁止用于任何违法、侵害他人合法权益等恶意的行为，禁
// | 止用于任何违反我国法律法规的一切项目研发，任何个人、组织和单位用于项目研发而产生的任何
// | 意外、疏忽、合约毁坏、诽谤、版权或知识产权侵犯及其造成的损失 (包括但不限于直接、间接、
// | 附带或衍生的损失等)，本团队不承担任何法律责任，本软件框架只能用于公司和个人内部的
// | 法律所允许的合法合规的软件产品研发，详细见https://www.modulithshop.cn/policy
// +----------------------------------------------------------------------
package com.suisung.shopsuite.trade.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.suisung.shopsuite.account.model.entity.UserDistribution;
import com.suisung.shopsuite.account.model.entity.UserInfo;
import com.suisung.shopsuite.account.repository.UserInfoRepository;
import com.suisung.shopsuite.account.service.UserDistributionService;
import com.suisung.shopsuite.account.service.WxQrCodeService;
import com.suisung.shopsuite.common.api.ResultCode;
import com.suisung.shopsuite.common.api.StateCode;
import com.suisung.shopsuite.common.components.poster.PromotePoster;
import com.suisung.shopsuite.common.components.poster.core.impl.PosterDefaultImpl;
import com.suisung.shopsuite.common.consts.ConstantConfig;
import com.suisung.shopsuite.common.exception.BusinessException;
import com.suisung.shopsuite.common.utils.*;
import com.suisung.shopsuite.core.consts.ConstantRedis;
import com.suisung.shopsuite.core.web.service.RedisService;
import com.suisung.shopsuite.pay.model.entity.*;
import com.suisung.shopsuite.pay.model.req.WithdrawAddReq;
import com.suisung.shopsuite.pay.model.vo.MoneyVo;
import com.suisung.shopsuite.pay.repository.*;
import com.suisung.shopsuite.pay.service.DistributionCommissionService;
import com.suisung.shopsuite.sys.service.ConfigBaseService;
import com.suisung.shopsuite.trade.model.entity.DistributionGeneratedCommission;
import com.suisung.shopsuite.trade.model.entity.DistributionOrder;
import com.suisung.shopsuite.trade.model.input.PosterInput;
import com.suisung.shopsuite.trade.model.output.PosterOutput;
import com.suisung.shopsuite.trade.model.vo.WithdrawVo;
import com.suisung.shopsuite.trade.repository.DistributionGeneratedCommissionRepository;
import com.suisung.shopsuite.trade.repository.DistributionOrderRepository;
import com.suisung.shopsuite.trade.service.DistributionOrderService;
import com.suisung.shopsuite.trade.service.DistributionService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

import static com.suisung.shopsuite.common.utils.I18nUtil.__;

/**
 * <p>
 * 分销服务类
 * </p>
 *
 * @author Xinze
 * @since 2021-07-03
 */
@Repository
public class DistributionServiceImpl implements DistributionService {
    private static final Logger logger = LoggerFactory.getLogger(DistributionServiceImpl.class);

    @Autowired
    private UserInfoRepository userInfoRepository;

    @Autowired
    private ConfigBaseService configBaseService;

    @Autowired
    private UserDistributionService userDistributionService;

    @Autowired
    private DistributionCommissionService distributionCommissionService;

    @Autowired
    private DistributionCommissionRepository distributionCommissionRepository;

    @Autowired
    private DistributionGeneratedCommissionRepository distributionGeneratedCommissionRepository;

    @Autowired
    private DistributionOrderRepository distributionOrderRepository;

    @Autowired
    private DistributionOrderService distributionOrderService;

    @Autowired
    private DistributionWithdrawRepository distributionWithdrawRepository;

    @Autowired
    private UserResourceRepository userResourceRepository;

    @Autowired
    private ConsumeWithdrawRepository consumeWithdrawRepository;

    @Autowired
    private WxQrCodeService wxQrCodeService;

    @Value("${url.h5}")
    private String base_ip;

    @Autowired
    private ThreadPoolExecutor executor;

    @Autowired
    private RedisService redisService;

    @Resource
    private UserPayRepository userPayRepository;

    @Override
    public Map index(Integer userId) {
        Map data = new HashMap();

        UserInfo userInfo = userInfoRepository.get(userId);

        CompletableFuture<Void> indexFuture1 = CompletableFuture.runAsync(() -> {
            data.put("base", userInfo);

            Map member_info = new HashMap();
            data.put("member_info", member_info);

            // 读取用户身份
            UserDistribution userDistribution = userDistributionService.get(userId);

            if (ObjectUtil.isEmpty(userDistribution)) {
                userDistribution = new UserDistribution();
            }

            data.put("user_role", userDistribution);

            // 累计用户
            long all_num = userDistributionService.getChildNum(userId, null, null);

            data.put("all_num", all_num);
        }, executor);

        CompletableFuture<Void> indexFuture2 = CompletableFuture.runAsync(() -> {
            TimeRange month = TimeUtil.month();

            // 当月用户
            long month_num = userDistributionService.getChildNum(userId, month.getStart(), month.getEnd());
            data.put("month_num", month_num);

            // 推广员历史总佣金
            DistributionCommission user_commission_row = distributionCommissionService.get(userId);
            if (user_commission_row != null) {
                BigDecimal commission_buy_amount_0 = user_commission_row.getCommissionBuyAmount0();
                BigDecimal commission_buy_amount_1 = user_commission_row.getCommissionBuyAmount1();
                BigDecimal commission_buy_amount_2 = user_commission_row.getCommissionBuyAmount2();

                float commission_buy_amount = NumberUtil.add(commission_buy_amount_0, commission_buy_amount_1, commission_buy_amount_2).floatValue();
                data.put("commission_buy_amount", commission_buy_amount);

                // 市区代理
                data.put("commission_buy_da", NumberUtil.round(user_commission_row.getCommissionBuyDa(), 2));
                data.put("commission_buy_ca", NumberUtil.round(user_commission_row.getCommissionBuyCa(), 2));
                data.put("commission_directseller_da", NumberUtil.round(user_commission_row.getCommissionDirectsellerDa(), 2));
                data.put("commission_directseller_ca", NumberUtil.round(user_commission_row.getCommissionDirectsellerCa(), 2));

                // 合伙人
                data.put("commission_partner_buy_trade", NumberUtil.round(user_commission_row.getCommissionPartnerBuyTrade(), 2));
                data.put("commission_partner_directseller_trade", NumberUtil.round(user_commission_row.getCommissionPartnerDirectsellerTrade(), 2));

                data.put("commission_buy_amount_0", NumberUtil.round(user_commission_row.getCommissionBuyAmount0(), 2));
                data.put("commission_directseller_amount_0", NumberUtil.round(user_commission_row.getCommissionDirectsellerAmount0(), 2));

                // 当前可用余额
                BigDecimal _commission_buy_amount = Convert.toBigDecimal(data.get("commission_buy_amount"));
                BigDecimal commission_buy_settled = user_commission_row.getCommissionBuySettled();
                BigDecimal commission_settled = user_commission_row.getCommissionSettled();
                BigDecimal commission_amount = user_commission_row.getCommissionAmount();

                data.put("user_commission_buy", NumberUtil.sub(_commission_buy_amount, commission_buy_settled).floatValue());
                data.put("user_commission_now", NumberUtil.sub(commission_amount, commission_settled).floatValue());
                data.put("commission_amount", commission_amount.floatValue());
            } else {
                data.put("user_commission_buy", BigDecimal.ZERO);
                data.put("user_commission_now", BigDecimal.ZERO);
                data.put("commission_amount", BigDecimal.ZERO);
            }
        }, executor);

        // 本月预计佣金
        // sql 统计
        CompletableFuture<Void> indexFuture3 = CompletableFuture.runAsync(() -> {
            TimeRange month = TimeUtil.month();
            float month_commission_buy = distributionOrderRepository.calCommission(userId, null, month.getStart(), month.getEnd());
            data.put("month_commission_buy", month_commission_buy);

            // 总订单
            QueryWrapper<DistributionOrder> orderQueryWrapper = new QueryWrapper<>();
            orderQueryWrapper.eq("user_id", userId);
            long order_num = distributionOrderRepository.count(orderQueryWrapper);
            data.put("order_num", order_num);

            // 当月订单数
            orderQueryWrapper.gt("uo_time", month.getStart());
            orderQueryWrapper.le("uo_time", month.getEnd());
            long order_month_num = distributionOrderRepository.count(orderQueryWrapper);
            data.put("order_month_num", order_month_num);

            data.put("commission_buy_amount", NumberUtil.round(Convert.toBigDecimal(data.get("commission_buy_amount"), BigDecimal.ZERO), 2));
            data.put("user_commission_buy", NumberUtil.round(Convert.toBigDecimal(data.get("user_commission_buy"), BigDecimal.ZERO), 2));
            data.put("user_commission_now", NumberUtil.round(Convert.toBigDecimal(data.get("user_commission_now"), BigDecimal.ZERO), 2));

            String user_nickname = userInfo.getUserNickname();
            data.put("westore_name", String.format("%s的小店", user_nickname));
        }, executor);

        try {
            CompletableFuture.allOf(indexFuture1, indexFuture2, indexFuture3).get();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return data;
    }

    @Override
    public Map getCommissionTimeline(Integer userId) {
        Map data = distributionOrderRepository.getCommissionTimeline(7, userId, false);

        return data;
    }


    /**
     * 增加上级
     */
    private void fixParentInfo(List<Map> items) {

        List<Integer> user_ids = items.stream().map(s -> Convert.toInt(s.get("user_id"))).distinct().collect(Collectors.toList());
        List<UserDistribution> plantformUserList = userDistributionService.gets(user_ids);
        List<Map> platform_user_rows = Convert.toList(Map.class, plantformUserList);

        //platform_user_rows = accountService.fixUserAvatar(platform_user_rows, false);
        for (Map item : items) {
            Integer user_id = (Integer) item.get("user_id");
            Optional<Map> plantformOpl = platform_user_rows.stream().filter(s -> ObjectUtil.equal(user_id, Convert.toInt(s.get("user_id")))).findFirst();
            Map plantform = plantformOpl.orElseGet(HashMap::new);

            item.put("p_name", plantform.get("user_parent_nickname"));
        }
    }

    @Override
    public Page<DistributionGeneratedCommission> listsCommission(Integer userId, Integer ugcLevel, Integer page, Integer size) {
        QueryWrapper<DistributionGeneratedCommission> column_row = new QueryWrapper<>();
        column_row.eq("user_parent_id", userId);
        column_row.eq("ugc_level", ugcLevel);

        Page<DistributionGeneratedCommission> lists = distributionGeneratedCommissionRepository.lists(column_row, page, size);

        List<Integer> buyUserIds = lists.getRecords().stream().map(DistributionGeneratedCommission::getUserId).distinct().collect(Collectors.toList());
        List<Integer> userParentId = lists.getRecords().stream().map(DistributionGeneratedCommission::getUserParentId).distinct().collect(Collectors.toList());

        buyUserIds.addAll(userParentId);

        //买家用户信息
        List<UserInfo> userInfos = userInfoRepository.gets(buyUserIds);
        Map<Integer, UserInfo> userInfoMap = new HashMap<>();

        if (CollectionUtil.isNotEmpty(userInfos)) {
            userInfoMap = userInfos.stream().collect(Collectors.toMap(UserInfo::getUserId, UserInfo -> UserInfo, (k1, k2) -> k1));
        }

        if (CollUtil.isNotEmpty(userInfoMap)) {
            for (DistributionGeneratedCommission item : lists.getRecords()) {
                UserInfo userInfo = userInfoMap.get(item.getUserId());

                if (userInfo != null) {
                    item.setUserAvatar(userInfo.getUserAvatar());
                    item.setUserNickname(userInfo.getUserNickname());
                }

                if (CheckUtil.isNotEmpty(item.getUserParentId())) {
                    UserInfo parentUser = userInfoMap.get(item.getUserParentId());

                    if (parentUser != null) {
                        item.setParentNickname(parentUser.getUserNickname());
                    }
                }
            }
        }

        return lists;
    }

    @Override
    public Map getCommissionNum(Integer userId) {

        Map data = new HashMap();
        Map user_fans = new HashMap();

        QueryWrapper<DistributionGeneratedCommission> query_level_1 = new QueryWrapper<>();
        query_level_1.eq("user_parent_id", userId);
        query_level_1.eq("ugc_level", 1);

        //不可以这样，根据where条件。'SELECT count(*) as num FROM ' . $this->_tableName;
        long level_1 = distributionGeneratedCommissionRepository.count(query_level_1);
        user_fans.put("level_1", level_1);

        QueryWrapper<DistributionGeneratedCommission> query_level_2 = new QueryWrapper<>();
        query_level_2.eq("user_parent_id", userId);
        query_level_2.eq("ugc_level", 2);
        long level_2 = distributionGeneratedCommissionRepository.count(query_level_2);
        user_fans.put("level_2", level_2);

        QueryWrapper<DistributionGeneratedCommission> query_level_3 = new QueryWrapper<>();
        query_level_3.eq("user_parent_id", userId);
        query_level_3.eq("ugc_level", 3);
        long level_3 = distributionGeneratedCommissionRepository.count(query_level_3);
        user_fans.put("level_3", level_3);

        data.put("user_fans", user_fans);

        return data;
    }


    /**
     * 推广海报
     *
     * @return
     */
    @Override
    public PosterOutput poster(PosterInput posterDTO) {
        Integer userId = posterDTO.getUserId();
        String cacheKey = ConstantRedis.Cache_NameSpace + "poster" + ConstantRedis.SEPARATOR + SecureUtil.md5(JSONUtil.toJsonStr(posterDTO));

        if (redisService.hasKey(cacheKey)) {
            return (PosterOutput) redisService.get(cacheKey);
        }

        Integer posterType = posterDTO.getPosterType();   // 海报类型:1-H5;2-小程序
        String posterName = Optional.ofNullable(posterDTO.getPosterName()).orElse(Optional.ofNullable(posterDTO.getPosterTitle()).orElse(configBaseService.getConfig("site_name")));
        String posterImg = posterDTO.getPosterImg();

        // 获取存文本
        Document postNameDoc = Jsoup.parse(posterName);
        posterName = postNameDoc.text();

        if (StrUtil.isBlank(posterImg)) {
            UserInfo userInfo = userInfoRepository.get(userId);
            String user_avatar = userInfo.getUserAvatar();
            posterImg = ObjectUtil.defaultIfBlank(user_avatar, configBaseService.getConfig("user_no_avatar"));
        }

        String posterPrice = "";

        // 图像是否输出价格字样
        if (CheckUtil.isEmpty(posterDTO.getPosterPrice())) {
            posterPrice = "";
        } else {
            posterPrice = String.format("%s %s", "¥", posterDTO.getPosterPrice());
        }


        String wap_url = "";
        String qrcode = "";
        PosterOutput output = new PosterOutput();
        wap_url = base_ip + "/pages/index/index?uid=" + userId;

        Map params = new HashMap();
        params.put("user_id", userId);
        params.put("posterType", posterType);
        params.put("posterName", posterName);


        // 构造路径
        String filename = SecureUtil.md5(JSONObject.toJSONString(params));
        String poster_path = String.format("%s/poster_%s/%s.png", UploadUtil.getUploadTempDir(), posterType, filename);
        String poster_url = String.format("%s/poster_%s/%s.png", ConstantConfig.URL_BASE + "/front/sys/upload/temp", posterType, filename);
        output.setPosterUrl(String.format("%s?rand=%s", poster_url, RandomUtil.randomString(13)));

        File qrcode_file = null;
        InputStream qrcode_stream = null;

        if (posterType == 1) {
            // 生成新版本H5 URL
            qrcode = configBaseService.qrcode(wap_url, 300, 300);

            // 移动端H5
            output.setInviteUrl(wap_url);
            output.setQrcode(qrcode);
            output.setDownloadUrl(qrcode + "&d=1");

        } else if (posterType == 2) {
            // 生成小程序 URL
            Map unlimitedMap = wxQrCodeService.getUnlimited(wap_url, params);
            qrcode = Convert.toStr(unlimitedMap.get("floder"));
            output.setInviteUrl(wap_url);
        }

        FileUtil.mkParentDirs(poster_path);
        File poster_file = FileUtil.file(poster_path);

        String qrcode_url = String.format("%s/poster_%s/%s-qrcode.png", ConstantConfig.URL_BASE + "/front/sys/upload/temp", posterType, filename);
        String qrcode_path = String.format("%s/poster_%s/%s-qrcode.png", UploadUtil.getUploadTempDir(), posterType, filename);

        //  todo 暂时写死
        String dir = "media/plantform/";
        filename = filename + "-qrcode.png";

        // 判断H5与小程序环境
        if (posterType == 1) {
            BufferedImage image = QrCodeUtil.generate(wap_url, 300, 300);
            // 生成二维码

            try {
                FileUtil.mkParentDirs(qrcode_path);
                qrcode_file = FileUtil.file(qrcode_path);
                ImageIO.write(image, "png", qrcode_file);
            } catch (IOException e) {
                throw new BusinessException(__("生成二维码失败！"));
            }

        } else if (posterType == 2) {
            qrcode_file = new File(qrcode);

            output.setQrcode(qrcode_url);
            output.setDownloadUrl(qrcode_url + "&d=1");
        }

        if (CheckUtil.isNotEmpty(posterDTO.getPosterImg())) {
            // 生成产品图片
            File main_file = null;
            try {
                main_file = getFile(posterImg);
            } catch (Exception e) {
                throw new BusinessException(__("图片不存在！"));
            }

            String plantform_poster_bg = "";
            if (StrUtil.isNotBlank(posterPrice)) {
                // 产品海报
                plantform_poster_bg = configBaseService.getConfig("product_poster_bg");
            } else {
                // 推广海报
                plantform_poster_bg = configBaseService.getConfig("plantform_poster_bg");
            }

            // 绘制海报图
            try {
                BufferedImage background = ImageIO.read(NetworkUtil.urlToInputSteam(plantform_poster_bg));
                BufferedImage qrcodeImage = null;
                qrcodeImage = ImageIO.read(qrcode_file);

                BufferedImage productImage = ImageIO.read(main_file);
                PromotePoster poster = PromotePoster.builder()
                        .backgroundImage(background)
                        .qrcodeImage(qrcodeImage)
                        .productName(posterName)
                        .productPrice(posterPrice)
                        .build();

                if (StrUtil.isNotBlank(posterPrice)) {
                    // 产品海报
                    poster.setProductImage(productImage);
                } else {
                    // 推广海报
                    poster.setPlantformImage(productImage);
                }

                PosterDefaultImpl<PromotePoster> impl = new PosterDefaultImpl<>();
                BufferedImage bufferedImage = impl.annotationDrawPoster(poster).draw(null);

                ImageIO.write(bufferedImage, "png", poster_file);
            } catch (Exception e) {
                throw new BusinessException(__("生成海报失败！"));
            }
        }

        redisService.set(cacheKey, output);

        return output;
    }

    @Override
    public WithdrawVo withdraw(Integer userId) {
        WithdrawVo withdrawVo = new WithdrawVo();
        // 推广员历史总佣金
        DistributionCommission distributionCommission = distributionCommissionService.get(userId);
        if (distributionCommission != null) {
            BigDecimal commissionAmount = distributionCommission.getCommissionAmount();
            BigDecimal commissionBuyAmount0 = distributionCommission.getCommissionBuyAmount0();
            BigDecimal commissionBuyAmount1 = distributionCommission.getCommissionBuyAmount1();
            BigDecimal commissionBuyAmount2 = distributionCommission.getCommissionBuyAmount2();
            BigDecimal commissionBuyAmount = NumberUtil.add(commissionBuyAmount0, commissionBuyAmount1, commissionBuyAmount2);

            // 当前可用余额
            BigDecimal commissionBuySettled = distributionCommission.getCommissionBuySettled();
            BigDecimal commissionSettled = distributionCommission.getCommissionSettled();
            BigDecimal userCommissionBuy = NumberUtil.sub(commissionBuyAmount, commissionBuySettled);
            BigDecimal userCommissionNow = NumberUtil.sub(commissionAmount, commissionSettled);

            BigDecimal plantformFxWithdrawMinAmount = configBaseService.getConfig("plantform_fx_withdraw_min_amount", BigDecimal.ZERO);
            BigDecimal withdrawMinAmount = configBaseService.getConfig("withdraw_min_amount", BigDecimal.ZERO);
            Float withdrawReceivedDay = configBaseService.getConfig("withdraw_received_day", 0f);
            BigDecimal withdrawMonthday = configBaseService.getConfig("withdraw_monthday", BigDecimal.ZERO);
            BigDecimal withdrawFeeRate = configBaseService.getConfig("withdraw_fee_rate", BigDecimal.ZERO);
            withdrawVo = new WithdrawVo(plantformFxWithdrawMinAmount, plantformFxWithdrawMinAmount, withdrawMinAmount,
                    withdrawReceivedDay, withdrawMonthday, withdrawFeeRate, NumberUtil.round(commissionBuyAmount, 2),
                    NumberUtil.round(userCommissionBuy, 2), NumberUtil.round(userCommissionNow, 2), NumberUtil.round(commissionAmount, 2));
        }

        return withdrawVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean doWithdraw(Integer userId) {
        // 推广员历史总佣金
        DistributionCommission distributionCommission = distributionCommissionService.get(userId);

        if (distributionCommission == null) {
            throw new BusinessException(__("推广员及收益表为空！"));
        }
        BigDecimal commissionAmount = distributionCommission.getCommissionAmount();
        // 当前可用余额
        BigDecimal commissionSettled = distributionCommission.getCommissionSettled();
        BigDecimal userCommissionNow = NumberUtil.sub(commissionAmount, commissionSettled);
        BigDecimal plantformFxWithdrawMinAmount = configBaseService.getConfig("plantform_fx_withdraw_min_amount", BigDecimal.ZERO);

        if (userCommissionNow.compareTo(BigDecimal.ZERO) > 0 && userCommissionNow.compareTo(plantformFxWithdrawMinAmount) >= 0) {
            doWithdraw(userId, userCommissionNow);
        } else {
            throw new BusinessException(__("佣金余额小于最小提现金额"));
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean doWithdraw(Integer userId, BigDecimal userCommissionNow) {
        boolean plantformCommissionWithdrawMode = configBaseService.getConfig("plantform_commission_withdraw_mode", false);

        if (plantformCommissionWithdrawMode) {
            throw new BusinessException(__("请使用佣金提现模式"));
        }
        DistributionCommission distributionCommission = distributionCommissionService.get(userId);

        if (distributionCommission == null) {
            throw new BusinessException(__("推广员及收益表为空！"));
        }
        distributionCommission.setCommissionSettled(NumberUtil.add(distributionCommission.getCommissionSettled(), userCommissionNow));

        if (!distributionCommissionRepository.edit(distributionCommission)) {
            throw new BusinessException(__("保存佣金结算数据失败"));
        }

        boolean autoWithdraw = configBaseService.getConfig("plantform_fx_auto_withdraw", false);
        // 添加提现记录到withdraw
        DistributionWithdraw distributionWithdraw = new DistributionWithdraw();
        distributionWithdraw.setUserId(userId);
        distributionWithdraw.setDuwAmount(userCommissionNow);
        distributionWithdraw.setDuwTime(new Date().getTime());
        distributionWithdraw.setDuwState(autoWithdraw);

        if (!distributionWithdrawRepository.add(distributionWithdraw)) {
            throw new BusinessException(__("保存佣金结算记录失败"));
        }

        // 是否需要进行审核
        if (autoWithdraw) {
            MoneyVo moneyVo = new MoneyVo();
            moneyVo.setUserId(userId);
            moneyVo.setRecordTotal(userCommissionNow);
            moneyVo.setTradeTypeDeposit(StateCode.TRADE_TYPE_COMMISSION);
            moneyVo.setRecordDesc(__("佣金转余额"));
            moneyVo.setPaymentTypeId(StateCode.PAYMENT_TYPE_ONLINE);
            moneyVo.setRecordCommissionFee(BigDecimal.ZERO);
            moneyVo.setOrderId(distributionWithdraw.getDuwId().toString());

            if (!userResourceRepository.money(moneyVo)) {
                throw new BusinessException(String.format(__("duw_id : %s 自动审核失败"), distributionWithdraw.getDuwId().toString()));
            }
        }

        return true;
    }

    /**
     * 佣金提现
     *
     * @param withdrawAddReq
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean doWithdrawMoney(WithdrawAddReq withdrawAddReq) {
        boolean plantformCommissionWithdrawMode = configBaseService.getConfig("plantform_commission_withdraw_mode", false);

//        if (!plantformCommissionWithdrawMode) {
//            throw new BusinessException(__("请使用提现到余额模式"));
//        }
        Integer userId = withdrawAddReq.getUserId();
        //推广员历史总佣金
        DistributionCommission distributionCommission = distributionCommissionService.get(userId);

        if (distributionCommission == null) {
            throw new BusinessException(__("推广员及收益表为空！"));
        }
        // 佣金总额:历史总额度
        BigDecimal commissionAmount = distributionCommission.getCommissionAmount();
        // 当前可用余额
        BigDecimal commissionSettled = distributionCommission.getCommissionSettled();
        // 佣金总额:历史总额度 - 当前可用余额
        BigDecimal userCommissionNow = NumberUtil.sub(commissionAmount, commissionSettled);
        // 配置项 最低提现金额 10
        BigDecimal plantformFxWithdrawMinAmount = configBaseService.getConfig("plantform_fx_withdraw_min_amount", BigDecimal.ZERO);

        if (userCommissionNow.compareTo(BigDecimal.ZERO) > 0 && userCommissionNow.compareTo(plantformFxWithdrawMinAmount) >= 0) {

            distributionCommission.setCommissionSettled(NumberUtil.add(distributionCommission.getCommissionSettled(), userCommissionNow));

            if (!distributionCommissionRepository.edit(distributionCommission)) {
                throw new BusinessException(__("保存佣金结算数据失败"));
            }
            ConsumeWithdraw consumeWithdraw = new ConsumeWithdraw();
            consumeWithdraw.setUserId(userId);// 用户编号
            consumeWithdraw.setStoreId(0);// 店铺编号
            consumeWithdraw.setOrderId("");
            consumeWithdraw.setReturnId("");// 所属订单
            consumeWithdraw.setWithdrawAmount(userCommissionNow);// 提现额度
            consumeWithdraw.setWithdrawState(0);// 是否成功(BOOL):0-申请中;1-提现通过
            consumeWithdraw.setWithdrawDesc(withdrawAddReq.getWithdrawDesc());// 描述
            consumeWithdraw.setWithdrawBank(withdrawAddReq.getWithdrawBank()); // 银行
            consumeWithdraw.setWithdrawMobile(withdrawAddReq.getWithdrawMobile());// 电话
            consumeWithdraw.setWithdrawAccountNo(withdrawAddReq.getWithdrawAccountNo());// 银行账户
            consumeWithdraw.setWithdrawAccountName(withdrawAddReq.getWithdrawAccountName());// 开户名称
            consumeWithdraw.setWithdrawTime(new Date().getTime());
            consumeWithdraw.setSubsiteId(0);
            consumeWithdraw.setWithdrawMode(1);
            doCommissionWithdraw(consumeWithdraw);
        } else {
            throw new BusinessException(__("佣金余额小于最小提现金额"));
        }

        return false;
    }


    /*
    * 余额提现
    * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean balanceCashOut(WithdrawAddReq withdrawAddReq) {
        Integer userId = withdrawAddReq.getUserId();

        //判断余额是否足够，不够报错！
        UserResource userResourceBuy = userResourceRepository.get(userId);

        if (userResourceBuy == null) {
            throw new BusinessException(__("推广员及余额表为空！"));
        }

        /*校验支付密码*/
        checkPayPasswd(withdrawAddReq.getUserId(), withdrawAddReq.getPassword());

        /*当前用户余额*/
        BigDecimal commissionAmount = userResourceBuy.getUserMoney();

        /*配置项中限制最小提现余额 10*/
        BigDecimal plantformFxWithdrawMinAmount = configBaseService.getConfig("plantform_fx_withdraw_min_amount", BigDecimal.ZERO);

        /*冻结金额*/
        BigDecimal userMoneyFrozen = userResourceBuy.getUserMoneyFrozen();


        if (commissionAmount.compareTo(BigDecimal.ZERO) > 0 && commissionAmount.compareTo(plantformFxWithdrawMinAmount) >= 0 && commissionAmount.compareTo(withdrawAddReq.getWithdrawAmount()) >= 0) {
//            userResourceBuy.setUserMoneyFrozen(NumberUtil.add(userMoneyFrozen,withdrawAddReq.getWithdrawAmount()));

            if (!userResourceRepository.edit(userResourceBuy)) {
                throw new BusinessException(__("保存余额结算数据失败"));
            }

            ConsumeWithdraw consumeWithdraw = new ConsumeWithdraw();
            consumeWithdraw.setUserId(userId);// 用户编号
            consumeWithdraw.setStoreId(0);// 店铺编号
            consumeWithdraw.setOrderId("");
            consumeWithdraw.setReturnId("");// 所属订单
            consumeWithdraw.setWithdrawAmount(withdrawAddReq.getWithdrawAmount());// 提现额度
            consumeWithdraw.setWithdrawState(0);// 是否成功(BOOL):0-申请中;1-提现通过
            consumeWithdraw.setWithdrawDesc(withdrawAddReq.getWithdrawDesc());// 描述
            consumeWithdraw.setWithdrawBank(withdrawAddReq.getWithdrawBank()); // 银行
            consumeWithdraw.setWithdrawMobile(withdrawAddReq.getWithdrawMobile());// 电话
            consumeWithdraw.setWithdrawAccountNo(withdrawAddReq.getWithdrawAccountNo());// 银行账户
            consumeWithdraw.setWithdrawAccountName(withdrawAddReq.getWithdrawAccountName());// 开户名称
            consumeWithdraw.setWithdrawTime(new Date().getTime());
            consumeWithdraw.setSubsiteId(0);
            consumeWithdraw.setWithdrawMode(0);// 余额提现
            doCommissionWithdraw(consumeWithdraw);

        } else {
            throw new BusinessException(__("余额小于最小提现金额"));
        }

        return false;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean doCommissionWithdraw(ConsumeWithdraw consumeWithdraw) {
        //提现月日期
        String withdrawMonthday = configBaseService.getConfig("withdraw_monthday", "");
        List<Integer> withdrawMonthdayRows = Convert.toList(Integer.class, withdrawMonthday);
        int no = DateUtil.dayOfMonth(new Date());

        if (!withdrawMonthdayRows.contains(no)) {
            throw new BusinessException(String.format(__("每月: %s 日可以申请提现！"), withdrawMonthday));
        }

        BigDecimal withdrawAmount = consumeWithdraw.getWithdrawAmount();
        if (ObjectUtil.compare(withdrawAmount, BigDecimal.ZERO) <= 0) {
            throw new BusinessException(__("提现额度有误！"));
        }

        BigDecimal plantformFxWithdrawMinAmount = configBaseService.getConfig("plantform_fx_withdraw_min_amount", BigDecimal.ZERO);
        if (ObjectUtil.compare(withdrawAmount, plantformFxWithdrawMinAmount) < 0) {
            throw new BusinessException(String.format(__("最低提现额度为: %f"), plantformFxWithdrawMinAmount));
        }

        if (!consumeWithdrawRepository.add(consumeWithdraw)) {
            throw new BusinessException(__("保存提现申请数据失败！"));
        }

        return true;
    }

    public void checkPayPasswd(Integer userId, String password) {

        UserPay userPay = userPayRepository.get(userId);
        if (userPay != null && StrUtil.isNotBlank(userPay.getUserPayPasswd())) {

            String userPaySalt = userPay.getUserPaySalt();
            String saltPassword = SecureUtil.md5(userPaySalt + SecureUtil.md5(password));

            if (!StrUtil.equals(saltPassword, userPay.getUserPayPasswd())) {
                throw new BusinessException(__("支付密码错误！"));
            }
        } else {
            throw new BusinessException(ResultCode.PAY_PWD_FAILED);
        }
    }

    private List<Map> fixCommission(List<Map> items) {

        if (CollUtil.isNotEmpty(items)) {
            List<Integer> user_ids = items.stream().map(s -> Convert.toInt(s.get("user_id"))).distinct().collect(Collectors.toList());
            List<DistributionCommission> user_commission_rows = distributionCommissionService.gets(user_ids);

            items.forEach(item -> {
                Integer user_id = Convert.toInt(item.get("user_id"));
                Optional<DistributionCommission> user_commission_rows_Opt = user_commission_rows.stream().filter(s -> ObjectUtil.equal(s.getUserId(), user_id)).findFirst();
                if (user_commission_rows_Opt.isPresent()) {
                    DistributionCommission DistributionCommission = user_commission_rows_Opt.orElseGet(DistributionCommission::new);
                    Map map = Convert.toMap(Object.class, Object.class, DistributionCommission);
                    item.putAll(map);
                }

            });
        }
        return items;
    }

    public static File getFile(String url) throws Exception {
        //对本地文件命名
        URL aURL = new URL(url);
        String fileName = SecureUtil.md5(aURL.getFile());

        File file = null;

        URL urlfile;
        InputStream inStream = null;
        OutputStream os = null;
        try {
            file = File.createTempFile("net_url", fileName);
            //下载
            urlfile = new URL(url);
            inStream = urlfile.openStream();
            os = new FileOutputStream(file);

            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = inStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            throw new BusinessException(__("图片不存在！"));
        } finally {
            try {
                if (null != os) {
                    os.close();
                }
                if (null != inStream) {
                    inStream.close();
                }

            } catch (Exception e) {
                throw new BusinessException(__("图片不存在！"));
            }
        }

        return file;
    }


}
